﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Common.Model
{
    /// <summary>
    /// Implementation des Points aber einfach mit integers
    /// </summary>
    public class CPoint : CBase
    {
        public enum Direction { Top, TopLeft, TopRight, MiddleLeft, MiddleRight, BottomLeft, Bottom, BottomRight }

        #region getter / setter
        public int X { get; set; }
        public int Y { get; set; }

        #endregion

        #region konstruktor
        public CPoint()
        {
            X = 0;
            Y = 0;
        }

        public CPoint(int x, int y)
        {
            X = x;
            Y = y;
        }
        #endregion

        #region operator things
        public override int GetHashCode()
        {
            return X ^ Y;
        }

        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;

            if (this.GetType() != obj.GetType())
                return false;

            CPoint p = obj as CPoint;

            return p.X == this.X && p.Y == this.Y && p.GetHashCode() == this.GetHashCode();
        }

        public static bool operator ==(CPoint a, CPoint b){
            return a.Equals(b);
        }

        public static bool operator !=(CPoint a, CPoint b)
        {
            return !a.Equals(b);
        }

        public static CPoint operator +(CPoint a, CPoint b)
        {
            return new CPoint(a.X + b.X, a.Y + b.Y);
        }

        public static CPoint operator -(CPoint a, CPoint b)
        {
            return new CPoint(a.X - b.X, a.Y - b.Y);
        }
        #endregion

        /// <summary>
        /// geht vom aktuellen punkt ein feld in die entsprechende richtung und giebt den neuen punkt zurück
        /// </summary>
        /// <param name="d"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        public CPoint getNextPointInDirection(Direction d)
        {
            int x = this.X;
            int y = this.Y;
            switch (d)
            {
                case Direction.Top:
                    y--;
                    break;
                case Direction.TopLeft:
                    y--;
                    x--;
                    break;
                case Direction.TopRight:
                    x++;
                    y--;
                    break;
                case Direction.MiddleLeft:
                    x--;
                    break;
                case Direction.MiddleRight:
                    x++;
                    break;
                case Direction.BottomLeft:
                    y++;
                    x--;
                    break;
                case Direction.Bottom:
                    y++;
                    break;
                case Direction.BottomRight:
                    y++;
                    x++;
                    break;
                default:
                    break;
            }
            return new CPoint(x, y);
        }

        /// <summary>
        /// geht vom akteullen punkt ein feld in die entsprechende gegenrichtung und giebt den neuen punkt zurück
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        public CPoint getNextPointInOppositeDirection(Direction d)
        {
            int x = this.X;
            int y = this.Y;
            switch (d)
            {
                case Direction.Top:
                    y++;
                    break;
                case Direction.TopLeft:
                    y++;
                    x++;
                    break;
                case Direction.TopRight:
                    x--;
                    y++;
                    break;
                case Direction.MiddleLeft:
                    x++;
                    break;
                case Direction.MiddleRight:
                    x--;
                    break;
                case Direction.BottomLeft:
                    y--;
                    x++;
                    break;
                case Direction.Bottom:
                    y--;
                    break;
                case Direction.BottomRight:
                    y--;
                    x--;
                    break;
                default:
                    break;
            }
            return new CPoint(x, y);
        }

        public override string ToString()
        {
            return ToString(false);    
        }
        public string ToString(bool justXY, bool humanXY = false)
        {
            try
            {
                if (justXY)
                {
                    return (humanXY ? (X + 1) : X).ToString() + " | " + (humanXY ? (Y + 1) : Y).ToString();
                }
                else
                {
                    return "Point=[X=" + X.ToString() + ", Y=" + Y.ToString() + "]";
                }
            }
            catch
            {
                return base.ToString();
            }
        }
    }
}
